package cn.iocoder.boot.springai001.config;

import cn.iocoder.boot.springai001.service.DBService;
import cn.iocoder.boot.springai001.tools.CoalTools;
import cn.iocoder.boot.springai001.tools.DateTimeTools;
import cn.iocoder.boot.springai001.tools.ExecuteSqlTools;
import cn.iocoder.boot.springai001.tools.RequestApiTools;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.memory.repository.jdbc.JdbcChatMemoryRepository;
import org.springframework.ai.chat.memory.repository.jdbc.MysqlChatMemoryRepositoryDialect;
import org.springframework.ai.model.tool.DefaultToolCallingManager;
import org.springframework.ai.model.tool.ToolCallingManager;
import org.springframework.ai.support.ToolCallbacks;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.execution.ToolExecutionExceptionProcessor;
import org.springframework.ai.tool.resolution.ToolCallbackResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Slf4j
@Configuration
public class ChatClientConfig {

    @Resource
    private DataSource dataSource;

    @Bean
    public ChatMemoryRepository chatMemoryRepository() {
        return JdbcChatMemoryRepository.builder()
                .jdbcTemplate(new JdbcTemplate(dataSource))
                .dialect(new MysqlChatMemoryRepositoryDialect())
                .build();
    }

    @Bean
    public ChatMemory chatMemory(ChatMemoryRepository chatMemoryRepository) {
        return MessageWindowChatMemory
                .builder()
                .chatMemoryRepository(chatMemoryRepository)
                .maxMessages(100)
                .build();
    }

    @Bean
    public ChatClient chatClient(ChatClient.Builder chatClientBuilder, ChatMemory chatMemory,
                                 ToolCallbackProvider toolCallbackProvider, DBService dbService) {
        ToolCallback[] toolCallbacks = ToolCallbacks.from(
                new DateTimeTools(), new ExecuteSqlTools(dbService),
                new RequestApiTools(), new CoalTools());
        log.info("✅ 初始化 ChatClient，内部回调工具数量: {}", toolCallbacks.length);
        for (ToolCallback toolCallback : toolCallbacks) {
            log.info("  - 工具名称: {}, 描述: {}", toolCallback.getToolDefinition().name(),
                    toolCallback.getToolDefinition().description());
        }

        return chatClientBuilder.defaultAdvisors(
                        MessageChatMemoryAdvisor
                                .builder(chatMemory)
                                .build())
                .defaultToolCallbacks(toolCallbackProvider.getToolCallbacks())
                .defaultToolCallbacks(toolCallbacks)
                .defaultAdvisors(new SimpleLoggerAdvisor())
                .build();
    }

    @Bean
    public ToolCallingManager toolCallingManager(ToolCallbackResolver toolCallbackResolver,
                                                 ToolExecutionExceptionProcessor toolExecutionExceptionProcessor) {
        return DefaultToolCallingManager.builder()
                .toolCallbackResolver(toolCallbackResolver)
                .toolExecutionExceptionProcessor(toolExecutionExceptionProcessor)
                .build();
    }

    @Bean
    public DBService dbServer(DataSource dataSource) {
        return DBService.instance(dataSource);
    }

}
